﻿using System;
using System.IO;
using System.Xml;
using System.Text;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using Newtonsoft.Json.Linq;
using TrinityAPI.Base;
using TrinityAPI.Base.Tools;
using TrinityAPI.Base.Models;
using Microsoft.Reporting.WebForms;
using PdfSharp.Pdf;
using PdfSharp.Drawing;

namespace Express.ShunFeng
{
    public class CancelWaybill : IAction
    {
        private string courierCode;

        public JToken Invoke(JObject dataset, params JToken[] args)
        {
            var request = dataset.GetJsonObject("request");
            var constant = dataset.GetJsonObject("constant");
            var courierInfo = constant.GetNecessaryJsonObject("courierInfo", "constant");

            courierCode = request.GetNecessaryJsonObjectStringValue("courierCode", "request");
            var config = courierInfo.GetNecessaryJsonObject(courierCode, "constant.courierInfo");
            int apiType = config.GetJsonObjectIntValue("apiType", 0);

            var response = apiType == 0 ? CancelWaybillOrder(request, config) : CancelWaybillOrderNew(request, config);
            return response;
        }

        public JToken CancelWaybillOrderNew(JObject request, JObject config)
        {
            string path = string.IsNullOrWhiteSpace(courierCode) ? null : string.Format("constant.courierInfo.{0}", courierCode);
            string url = config.GetNecessaryJsonObjectStringValue("url", path);
            string appkey = config.GetNecessaryJsonObjectStringValue("appkey", path);
            string appsecret = config.GetNecessaryJsonObjectStringValue("appsecret", path);
            var timeout = config.GetJsonObjectIntValue("timeout", 30000);
            var proxy = config.GetJsonObjectValue("proxy");
            string orderId = request.GetNecessaryJsonObjectStringValue("orderid");

            JObject json = new JObject();
            json.Add("orderId", orderId);
            json.Add("dealType", 2);
            json.Add("language", "zh_CN");

            string serviceCode = "EXP_RECE_UPDATE_ORDER";
            string timestamp = GetTimeStamp(DateTime.Now).ToString();
            string msgData = ToUTF8(json.ToString(Newtonsoft.Json.Formatting.None));
            string msgDigest = Utils.MD5(UrlEncode(msgData + timestamp + appsecret), Encoding.UTF8, false, true);
            string param = string.Format("partnerID={0}&requestID={1}&serviceCode={2}&timestamp={3}&msgData={4}&msgDigest={5}",
                appkey,
                Guid.NewGuid().ToString("N"),
                serviceCode,
                timestamp,
                UrlEncode(msgData),
                msgDigest);

            try
            {
                LogHelper.Info("url: " + url, "SFEApiLog");
                LogHelper.Info("request: " + param, "SFEApiLog");
                var headers = new System.Collections.Generic.Dictionary<string, string>() { { "Content-Type", "application/x-www-form-urlencoded;charset=UTF-8" } };
                string result = HttpHelper.HttpWebRequest(url, param, "POST", timeout, headers, proxy?.ToString());
                LogHelper.Info("response: " + result, "SFEApiLog");

                var responseObject = JSONHelper.JsonToJObject(result);

                string code = responseObject.GetJsonObjectStringValue("apiResultCode");

                if (code.ToUpper() == "A1000")
                {
                    string apiResultData = responseObject.GetJsonObjectStringValue("apiResultData");
                    var apiResultObject = JSONHelper.JsonToJObject(apiResultData);
                    if (!apiResultObject.GetJsonObjectBooleanValue("success"))
                    {
                        return false;
                    }
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (BaseException ex)
            {
                if (!string.IsNullOrEmpty(ex.Message))
                    throw ex;
                throw new Exception(ex.Code);
            }
            catch (Exception ex)
            {
                LogHelper.Error("ShunFeng CancelWaybillOrderNew fail", ex, "SFEApiLog");
                throw new Exception("@E210001001");
            }
        }

        public JToken CancelWaybillOrder(JObject request, JObject config)
        {
            string path = string.IsNullOrWhiteSpace(courierCode) ? null : string.Format("constant.courierInfo.{0}", courierCode);
            string url = config.GetNecessaryJsonObjectStringValue("url", path);
            string appkey = config.GetNecessaryJsonObjectStringValue("appkey", path);
            string appsecret = config.GetNecessaryJsonObjectStringValue("appsecret", path);
            var timeout = config.GetJsonObjectIntValue("timeout", 30000);
            var proxy = config.GetJsonObjectValue("proxy");
            string orderId = request.GetNecessaryJsonObjectStringValue("orderid");
            string deliverOrderId = request.GetJsonObjectStringValue("deliverOrderId", orderId);

            StringBuilder xml = new StringBuilder();
            xml.Append("<?xml version='1.0' encoding='UTF-8'?>");
            xml.Append("<Request service='OrderConfirmService' lang='zh-CN'>");
            xml.AppendFormat("<Head>{0}</Head>", appkey);
            xml.Append("<Body>");
            xml.Append("<OrderConfirm ");
            xml.AppendFormat("orderid='{0}' ", XmlEscape(deliverOrderId));
            xml.AppendFormat("dealtype='{0}' ", "2");
            xml.Append(">");
            xml.Append("</OrderConfirm>");
            xml.Append("</Body>");
            xml.Append("</Request>");

            string utf8String = ToUTF8(xml.ToString());
            string verifyCode = Utils.MD5(utf8String + appsecret, Encoding.UTF8, false, true);
            string param = string.Format("xml={0}&verifyCode={1}", System.Web.HttpUtility.UrlEncode(utf8String), System.Web.HttpUtility.UrlEncode(verifyCode));

            try
            {
                LogHelper.Info("url: " + url, "SFEApiLog");
                LogHelper.Info("request: " + param, "SFEApiLog");
                string result = HttpHelper.HttpWebRequest(url, param, "POST", timeout, null, proxy?.ToString());
                LogHelper.Info("response: " + result, "SFEApiLog");

                XmlDocument doc = new XmlDocument();
                doc.LoadXml(result);

                XmlNode Head = doc.SelectSingleNode("/Response/Head");

                string status = Head.InnerText;

                if (status.ToUpper() == "OK")
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (BaseException ex)
            {
                if (!string.IsNullOrEmpty(ex.Message))
                    throw ex;
                throw new Exception(ex.Code);
            }
            catch (Exception ex)
            {
                LogHelper.Error("ShunFeng CancelWaybillOrder fail", ex, "SFEApiLog");
                throw new Exception("@E210001001");
            }
        }

        private static string XmlEscape(string s)
        {
            if (string.IsNullOrWhiteSpace(s)) return s;
            s = s.Replace("&", "&amp;");
            s = s.Replace("<", "&lt;");
            s = s.Replace("'", "&apos;");
            s = s.Replace(">", "&gt;");
            s = s.Replace("\"", "&quot;");
            return s;
        }

        public static string ToUTF8(string unicodeString)
        {
            UTF8Encoding utf8 = new UTF8Encoding();
            Byte[] encodedBytes = utf8.GetBytes(unicodeString);
            String decodedString = utf8.GetString(encodedBytes);
            return decodedString;
        }

        private static string UrlEncode(string str)
        {
            StringBuilder builder = new StringBuilder();
            foreach (char c in str)
            {
                if (c == '(')
                {
                    builder.Append("%28");
                }
                else if (c == ')')
                {
                    builder.Append("%29");
                }
                else
                {
                    string encoded = System.Web.HttpUtility.UrlEncode(c.ToString(), Encoding.UTF8);
                    if (encoded.Length > 1)
                    {
                        builder.Append(encoded.ToUpper());
                    }
                    else
                    {
                        builder.Append(c);
                    }
                }
            }
            return builder.ToString();
        }

        private static long GetTimeStamp(DateTime datetime)
        {
            if (datetime.Kind != DateTimeKind.Utc)
                datetime = datetime.ToUniversalTime();
            var epochTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            var span = (long)((datetime - epochTime).TotalSeconds);
            return span;
        }
    }
}
